package com.qcu.controller.user;

import com.alibaba.fastjson2.JSON;
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.AlipayConstants;
import com.alipay.api.internal.util.AlipaySignature;
import com.alipay.api.request.AlipayTradePagePayRequest;
import com.alipay.api.response.AlipayTradePagePayResponse;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.qcu.entity.HealthMenu;
import com.qcu.entity.OrderInfo;
import com.qcu.entity.PaymentInfo;
import com.qcu.mapper.OrderInfoMapper;
import com.qcu.service.ExaminationInfoService;
import com.qcu.service.HealthMenuService;
import com.qcu.service.OrderInfoService;
import com.qcu.service.PaymentInfoService;
import com.qcu.util.*;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.env.Environment;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.*;

import java.math.BigDecimal;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantLock;

/**
 * @Name: MyComputer
 * @ClassName OrderController
 * @Description:
 * @date 2025/4/9 13:57
 */
@Slf4j
@RestController
@RequestMapping("/user/pay")
public class OrderController {

    @Resource
    OrderInfoService orderInfoService;

    @Resource
    AlipayClient alipayClient;

    @Resource
    HealthMenuService healthMenuService;

    @Resource
    Environment config;

    @Resource
    PaymentInfoService paymentInfoService;

    @Resource
    OrderInfoMapper orderInfoMapper;

    @Resource
    private ExaminationInfoService examinationInfoService;

    @Resource
    RedisTemplate redisTemplate;

    // 线程锁, 保证线程安全
    private final ReentrantLock lock = new ReentrantLock();

    /**
     * 支付
     * @param productId 产品id
     * @param info 预约的信息
     * @return
     */
    @PostMapping("/{productId}")
    public Response pay(@PathVariable Integer productId, @RequestBody Map<String,Object> info) {
        try {

//            String menu = (String)redisTemplate.opsForValue().get("healthMenu");
//            if (menu != null && !menu.equals("")){
//                List<HealthMenu> healthMenus = JSON.parseArray(menu, HealthMenu.class);
//                HealthMenu healthMenu1 = healthMenus.stream().filter(healthMenu -> healthMenu.getId().equals(productId)).findFirst().orElse(null);
//
//            }


            // 获取用户id
            Map<String,Object> map = ThreadLocalUtil.get();
            Integer userId = (Integer) map.get("id");
            OrderInfo orderInfo = null;
            String con = "";
            // 查看该套餐时候已经预定
            if ((orderInfo = orderInfoService.getOne(new LambdaQueryWrapper<OrderInfo>().eq(OrderInfo::getProductId, productId).eq(OrderInfo::getUserId, userId).eq(OrderInfo::getStatus, "未支付").eq(OrderInfo::getInhabitantId, (String)info.get("inhabitantId")))) == null) {
                HealthMenu product = healthMenuService.getById(productId);
                con = product.getItem();
                orderInfo = new OrderInfo();
                orderInfo.setTitle(product.getName());
                orderInfo.setOrderNo(OrderNoUtils.getOrderNo());
                orderInfo.setProductId(productId);
                orderInfo.setPrice(product.getPrice());
                orderInfo.setStatus(OrderStatus.NOTPAY.getType());
                orderInfo.setUserId(userId);
                orderInfo.setInhabitantId((String) info.get("inhabitantId"));
                // 设置再前端获取的预约时间
                orderInfo.setTime(new SimpleDateFormat("yyyy-MM-dd").parse((String) info.get("time")));
                orderInfo.setName((String) info.get("name"));
                orderInfoService.save(orderInfo);
            }

            // 调用支付宝接口
            AlipayTradePagePayRequest request = new AlipayTradePagePayRequest();
            BigDecimal price = new BigDecimal(orderInfo.getPrice()).divide(new BigDecimal("100"));
            request.setBizContent("{" +
                    "    \"out_trade_no\":\"" + orderInfo.getOrderNo() + "\"," +
                    "    \"product_code\":\"FAST_INSTANT_TRADE_PAY\"," +
                    "    \"total_amount\":" + price + "," +
                    "    \"subject\":\"" + orderInfo.getTitle() + "\"" +
                    "  }");

            request.setNotifyUrl(config.getProperty("alipay.notify-url"));
            request.setReturnUrl(config.getProperty("alipay.return-url"));
            AlipayTradePagePayResponse response = alipayClient.pageExecute(request);
            if (response.isSuccess()){
                String body = response.getBody();

                return Response.success(body);
            }else {
                return Response.failure(ResponseCode.FAILURE, "调用支付宝接口失败");
            }


        } catch (AlipayApiException e) {
            throw new RuntimeException("创建支付交易失败");
        } catch (ParseException e) {
            throw new RuntimeException(e);
        }


    }


    @PostMapping("/notify")
    public String tradeNotify(@RequestParam Map<String, String> params){
        String result = "failure";
        try {
            // 异步通知验签
            boolean signVerified = AlipaySignature.rsaCheckV1(
                    params,
                    config.getProperty("alipay.alipay-public-key"),
                    AlipayConstants.CHARSET_UTF8,
                    AlipayConstants.SIGN_TYPE_RSA2
            );
            if (!signVerified){
                log.error("验签失败");
                return result;
            }
            log.info("验签成功");

            // 检查订单是否存在数据库
            String outTradeNo = params.get("out_trade_no");
            OrderInfo orderInfo = orderInfoService.getOne(new LambdaQueryWrapper<OrderInfo>().eq(OrderInfo::getOrderNo, outTradeNo));
            if (orderInfo == null){
                log.info("订单不存在");
                return result;
            }

            // 检查金额
            String totalAmount = params.get("total_amount");
            int totalAmountInt = new BigDecimal(totalAmount).multiply(new BigDecimal("100")).intValue();
            int totalFeeInt = new BigDecimal(orderInfo.getPrice()).intValue();
            if(totalAmountInt != totalFeeInt){
                log.error("金额校验失败");
                return result;
            }

            // 检查卖家id
            String sellerId = params.get("seller_id");
            String sellerIdProperty = config.getProperty("alipay.seller-id");
            if(!sellerId.equals(sellerIdProperty)){
                log.error("商家pid校验失败");
                return result;
            }

            // 检查appid
            String appId = params.get("app_id");
            String appIdProperty = config.getProperty("alipay.app-id");
            if(!appId.equals(appIdProperty)){
                log.error("appid校验失败");
                return result;
            }

            // 检查支付宝通知状态
            String tradeStatus = params.get("trade_status");
            if(!"TRADE_SUCCESS".equals(tradeStatus)){
                log.error("支付未成功");
                return result;
            }

            // 修改订单状态 记录日志
            log.info("处理订单");
            if (lock.tryLock()){
                try{
                    // 获取订单信息
                    OrderInfo order = orderInfoService.getOne(new LambdaQueryWrapper<OrderInfo>().eq(OrderInfo::getOrderNo, outTradeNo));
                    // 判断是否已经处理，保持接口幂等性
                    if (OrderStatus.NOTPAY.getType().equals(order.getStatus())){
                        orderInfoService.update(new LambdaUpdateWrapper<OrderInfo>().eq(OrderInfo::getOrderNo, outTradeNo).set(OrderInfo::getStatus, OrderStatus.SUCCESS.getType()));

                        log.info("订单处理完成");

                        //获取订单号
                        String orderNo = params.get("out_trade_no");
                        //业务编号
                        String transactionId = params.get("trade_no");

                        // 添加支付信息
                        String content = healthMenuService.getContent(orderNo);
                        String[] split = content.split("；");
                        HashMap<String, String> map = new HashMap<>();
                        for (String s : split){
                            map.put(s, "");
                        }

                        String s = JSON.toJSONString(map);

                        PaymentInfo paymentInfo = new PaymentInfo();
                        paymentInfo.setOrderNo(orderNo);
                        paymentInfo.setPaymentType(PayType.ALIPAY.getType());
                        paymentInfo.setTransactionId(transactionId);
                        paymentInfo.setTradeState(tradeStatus);
                        paymentInfo.setTradeType("电脑网站支付");
                        paymentInfo.setPayerTotal(String.valueOf(totalAmountInt));
                        paymentInfo.setContent(s);

                        paymentInfoService.save(paymentInfo);

                    }

                }finally {
                    lock.unlock();
                }
            }
            result = "success";

        } catch (AlipayApiException e) {
            throw new RuntimeException(e);
        }

        return result;
    }

    /**
     * 获取所有的体检项目
     * @return
     */
    @GetMapping("/getInfo")
    public Response getProductInfo(){

        String healthMenu = (String) redisTemplate.opsForValue().get("healthMenu");
        if (healthMenu != null){
            List<HealthMenu> healthMenus = JSON.parseArray(healthMenu, HealthMenu.class);
            return Response.success(healthMenus);
        }

        List<HealthMenu> list = healthMenuService.list();
        redisTemplate.opsForValue().set("healthMenu", JSON.toJSONString(list), 60, TimeUnit.MINUTES);

        return Response.success(list);
    }

}
